#include "dev_uart.h"
#include <cstdlib>

Dev_Uart::Dev_Uart(const string &devicename, const uint32_t baudRate):baudRate(baudRate)
{
    fd = open(devicename.c_str(),O_RDWR);
    if(fd == -1)
    {
        fprintf(stderr,"open %s failure.reason:%s\n",devicename.c_str(),strerror(errno));
        exit(EXIT_FAILURE);
    }
    fprintf(stdout, "open %s successful\n", devicename.c_str());
    // 初始化UART
    bool res = uartInit(baudRate);
    if (res)
    {
        cout << "uartInit successful" << endl;
    }
}


Dev_Uart::~Dev_Uart()
{
    if (fd > 0)
    {
        close(fd);
    }
}

bool Dev_Uart::uartInit(uint32_t baudRate) const
{
    struct termios tio;
    bzero(&tio, sizeof(tio)); //仅在支持 POSIX 标准的系统（如 Linux、macOS、BSD）中可用memset代替。

    // 1. 使能本地连接（CLOCAL）和接收使能（CREAD）
    tio.c_cflag |= CLOCAL | CREAD;
    // 2. 清除数据位长度的掩码（CSIZE），为后续设置数据位做准备
    tio.c_cflag &= ~CSIZE;

    // 3. 设置数据位为 8 位（CS8）
    tio.c_cflag |= CS8;
    // 4. 禁用奇偶校验（PARENB 是“允许奇偶校验”的标志，取反表示禁用）
    tio.c_cflag &= ~PARENB;
    // 5. 禁用 2 位停止位（CSTOPB 是“2 位停止位”的标志，取反表示使用 1 位停止位）
    tio.c_cflag &= ~CSTOPB;
    // 设置波特率
    switch (baudRate)
    {
        case 9600:
            // 设置终端输入波特
            cfsetispeed(&tio, B9600);
            // 设置终端输出波特
            cfsetospeed(&tio, B9600);
            break;
        case 57600:
            cfsetispeed(&tio, B57600);
            cfsetospeed(&tio, B57600);
            break;
        case 115200:
            cfsetispeed(&tio, B115200);
            cfsetospeed(&tio, B115200);
            break;
        default:
            fprintf(stderr, "The baudrate:%d is not support\n", baudRate);
            return false;
    }

    // VMIN=0 && VTIME > 0 设置超时时间，如果时间到了,uart中没有数据就会返回，返回结果为0
    tio.c_cc[VTIME] = 50; // 5s
    tio.c_cc[VMIN] = 0;

    // 清空I/O缓冲区
    tcflush(fd, TCIOFLUSH);

    // 设置uart并立即生效
    int ret = tcsetattr(fd, TCSANOW, &tio);
    if (ret == -1)
    {
        fprintf(stderr, "tcsetattr failure.reason:%s\n", strerror(errno));
        return false;
    }
    return true;
}


uint16_t Dev_Uart::readUartData(char *buf, const uint16_t size)
{
    ssize_t rbytes = read(fd, buf, size);
    if (rbytes == -1)
    {
        fprintf(stderr, "read uart data failure. reason:%s\n", strerror(errno));
        return -1;
    }
    return rbytes;
}

bool Dev_Uart::receiveFixedSizeData(char *buf, uint16_t size)
{
    uint16_t alreadySize = 0;
    while (alreadySize < size)
    {
        ssize_t rbytes = read(fd, buf + alreadySize, size - alreadySize);
        if (rbytes == -1)
        {
            return false;
        }
        alreadySize += rbytes;
        if (alreadySize == size)
        {
            break;
        }
        cout << "等待接收数据中..." << endl;
    }
    return true;
}

uint16_t Dev_Uart::writeUartData(char *buf, const uint16_t size)
{
    ssize_t wbytes = write(fd, buf, size);
    if (wbytes == -1)
    {
        fprintf(stderr, "write uart data failure. reason:%s\n", strerror(errno));
        return -1;
    }
    return wbytes;
}